package com.fhx.core.utils





/**
 * 身份证校验工具类
 */
object IDCardUtil {
    private var _codeError: String? = null

    // wi =2(n-1)(mod 11)
    val wi = intArrayOf(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1)
    // verify digit
    val vi = intArrayOf(1, 0, 'X'.toInt(), 9, 8, 7, 6, 5, 4, 3, 2)
    private val ai = IntArray(18)
    private val _areaCode = arrayOf(
        "11",
        "12",
        "13",
        "14",
        "15",
        "21",
        "22",
        "23",
        "31",
        "32",
        "33",
        "34",
        "35",
        "36",
        "37",
        "41",
        "42",
        "43",
        "44",
        "45",
        "46",
        "50",
        "51",
        "52",
        "53",
        "54",
        "61",
        "62",
        "63",
        "64",
        "65",
        "71",
        "81",
        "82",
        "91"
    )
    private var dateMap: HashMap<String, Int?>? = null
    private var areaCodeMap: HashMap<String, String?>? = null
    init {
        dateMap = HashMap()
        dateMap!!["01"] = 31
        dateMap!!["02"] = null
        dateMap!!["03"] = 31
        dateMap!!["04"] = 30
        dateMap!!["05"] = 31
        dateMap!!["06"] = 30
        dateMap!!["07"] = 31
        dateMap!!["08"] = 31
        dateMap!!["09"] = 30
        dateMap!!["10"] = 31
        dateMap!!["11"] = 30
        dateMap!!["12"] = 31
        areaCodeMap = HashMap()
        for (code in _areaCode){
            areaCodeMap!![code] = null
        }
    }

    // 验证身份证位数,15位和18位身份证
    fun verifyLength(code: String): Boolean {
        val length = code.length
        return if (length == 15 || length == 18) {
            true
        } else {
            _codeError = "错误：输入的身份证号不是15位和18位的"
            false
        }
    }

    // 判断地区码
    fun verifyAreaCode(code: String): Boolean {
        val areaCode = code.substring(0, 2)
        // Element child= _areaCodeElement.getChild("_"+areaCode);
        return if (areaCodeMap!!.containsKey(areaCode)) {
            true
        } else {
            _codeError = "错误：输入的身份证号的地区码(1-2位)[$areaCode]不符合中国行政区划分代码规定(GB/T2260-1999)"
            false
        }
    }

    // 判断月份和日期
    fun verifyBirthdayCode(code: String): Boolean { // 验证月份
        val month = code.substring(10, 12)
        val isEighteenCode = 18 == code.length
        if (!dateMap!!.containsKey(month)) {
            _codeError =
                ("错误：输入的身份证号" + (if (isEighteenCode) "(11-12位)" else "(9-10位)") + "不存在[" + month
                        + "]月份,不符合要求(GB/T7408)")
            return false
        }
        // 验证日期
        val dayCode = code.substring(12, 14)
        val day = dateMap!![month]
        val yearCode = code.substring(6, 10)
        val year = Integer.valueOf(yearCode)
        // 非2月的情况
        if (day != null) {
            if (Integer.valueOf(dayCode) > day || Integer.valueOf(dayCode) < 1) {
                _codeError =
                    ("错误：输入的身份证号" + (if (isEighteenCode) "(13-14位)" else "(11-13位)") + "[" + dayCode
                            + "]号不符合小月1-30天大月1-31天的规定(GB/T7408)")
                return false
            }
        } else { // 闰月的情况
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
                if (Integer.valueOf(dayCode) > 29 || Integer.valueOf(dayCode) < 1) {
                    _codeError =
                        ("错误：输入的身份证号" + (if (isEighteenCode) "(13-14位)" else "(11-13位)") + "[" + dayCode + "]号在"
                                + year + "闰年的情况下未符合1-29号的规定(GB/T7408)")
                    return false
                }
            } else {
                if (Integer.valueOf(dayCode) > 28 || Integer.valueOf(dayCode) < 1) {
                    _codeError =
                        ("错误：输入的身份证号" + (if (isEighteenCode) "(13-14位)" else "(11-13位)") + "[" + dayCode + "]号在"
                                + year + "平年的情况下未符合1-28号的规定(GB/T7408)")
                    return false
                }
            }
        }
        return true
    }

    // 验证身份除了最后位其他的是否包含字母
    fun containsAllNumber(code: String): Boolean {
        var str = ""
        if (code.length == 15) {
            str = code.substring(0, 15)
        } else if (code.length == 18) {
            str = code.substring(0, 17)
        }
        val ch = str.toCharArray()
        for (i in ch.indices) {
            if (ch[i] !in '0'..'9') {
                _codeError = "错误：输入的身份证号第" + (i + 1) + "位包含字母"
                return false
            }
        }
        return true
    }

    fun getCodeError(): String? {
        return _codeError
    }

    // 验证身份证
    fun verify(idcard: String): Boolean {
        _codeError = ""
        // 验证身份证位数,15位和18位身份证
        if (!verifyLength(idcard)) {
            return false
        }
        // 验证身份除了最后位其他的是否包含字母
        if (!containsAllNumber(idcard)) {
            return false
        }
        // 如果是15位的就转成18位的身份证
        var eifhteencard: String
        eifhteencard = if (idcard.length == 15) {
            uptoeighteen(idcard)
        } else {
            idcard
        }
        // 验证身份证的地区码
        if (!verifyAreaCode(eifhteencard)) {
            return false
        }
        // 判断月份和日期
        if (!verifyBirthdayCode(eifhteencard)) {
            return false
        }
        // 验证18位校验码,校验码采用ISO 7064：1983，MOD 11-2 校验码系统
        return verifyMOD(eifhteencard)
    }

    // 验证18位校验码,校验码采用ISO 7064：1983，MOD 11-2 校验码系统
    fun verifyMOD(code: String): Boolean {
        var code = code
        var verify = code.substring(17, 18)
        if ("x" == verify) {
            code = code.replace("x".toRegex(), "X")
            verify = "X"
        }
        val verifyIndex = getVerify(code)
        if (verify == verifyIndex) {
            return true
        }
        // int x=17;
// if(code.length()==15){
// x=14;
// }
        _codeError = "错误：输入的身份证号最末尾的数字验证码错误"
        return false
    }

    // 获得校验位
    fun getVerify(eightcardid: String): String {
        var eightcardid = eightcardid
        var remaining = 0
        if (eightcardid.length == 18) {
            eightcardid = eightcardid.substring(0, 17)
        }
        if (eightcardid.length == 17) {
            var sum = 0
            for (i in 0..16) {
                val k = eightcardid.substring(i, i + 1)
                ai[i] = k.toInt()
            }
            for (i in 0..16) {
                sum += wi[i] * ai[i]
            }
            remaining = sum % 11
        }
        return if (remaining == 2) "X" else vi[remaining].toString()
    }

    // 15位转18位身份证
    fun uptoeighteen(fifteencardid: String): String {
        var eightcardid = fifteencardid.substring(0, 6)
        eightcardid += "19"
        eightcardid += fifteencardid.substring(6, 15)
        eightcardid += getVerify(eightcardid)
        return eightcardid
    }
}